package com.chwl.framework.springboot.grpc;

import com.chwl.framework.grpc.discover.ServiceDiscoverService;
import com.chwl.framework.springboot.grpc.config.GrpcProperties;
import com.chwl.framework.springboot.grpc.service.CommonService;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.CommandLineRunner;

import java.util.Optional;

/**
 * gRPC Server 启动器
 */
public class GrpcServerRunner implements CommandLineRunner, DisposableBean {

    private static final Logger log = LoggerFactory.getLogger(GrpcServerRunner.class.getName());

    private final ServerBuilder<?> serverBuilder;

    private final CommonService commonService;

    private Server server;
    GrpcProperties properties;

    public GrpcServerRunner(ServerBuilder<?> serverBuilder, CommonService commonService, GrpcProperties properties) {
        this.serverBuilder = serverBuilder;
        this.commonService = commonService;
        this.properties = properties;
        //服务上报
        ServiceDiscoverService.getInstance().heartbeat(properties.getPort(), properties.getServiceNames());
    }


    @Override
    public void run(String... args) throws Exception {
        server = serverBuilder.addService(commonService).build().start();
        if (log.isInfoEnabled()) {
            log.info("GRPC Server started, listening on port:{} ", server.getPort());
        }
        startDaemonAwaitThread();
    }

    @Override
    public void destroy() {
        Optional.ofNullable(server).ifPresent(Server::shutdown);
        log.info("GRPC server stopped.");
    }

    private void startDaemonAwaitThread() {
        Thread awaitThread = new Thread(() -> {
            try {
                GrpcServerRunner.this.server.awaitTermination();
            } catch (Exception e) {
                log.error("GRPC server stopped fail,error message:{}", e.getMessage(), e);
            }
        });
        awaitThread.setDaemon(false);
        awaitThread.start();
    }

}